package com.ow.dva.config.handler;

import com.ow.dva.module.base.entity.json.RT;
import com.ow.dva.util.RequestUtil;
import org.apache.shiro.authz.UnauthorizedException;
import org.attoparser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.spel.SpelParseException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.thymeleaf.exceptions.TemplateInputException;
import org.thymeleaf.exceptions.TemplateProcessingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.SocketTimeoutException;

/**
 * 描述 : 全局异常拦截
 * 包名 : com.ow.dva.config.handler
 * 作者 : GaoXiang
 * 时间 : 18-11-12
 * 版本 : V1.0
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    //日志工具
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 拦截无资源访问
     * @param request 请求信息
     * @param e 异常信息
     * @return 返回处理结果
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)//指定拦截类型
    public RT noHandlerFound(HttpServletRequest request,Exception e){
        logger.warn("================== 「404 未找到资源路径」 ==================");
        logger.warn("请求路径：" + request.getServletPath());
        logger.warn("请求方式：" + request.getMethod());
        logger.warn("异常信息:" + e.getMessage());
        logger.warn("================== 「   异 常 结 束   」 ==================");
        return RT.error(RT.NO_RESOURCES_CODE,e.getMessage());
    }

    /**
     * 拦截错误的请求方式 例如post方法用get请求
     * @param request 请求信息
     * @param e 异常信息
     * @return 返回处理结果
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)//指定拦截类型
    public RT methodNotSupported(HttpServletRequest request,Exception e){
        logger.warn("================== 「500 不支持的请求方式」 ==================");
        logger.warn("请求路径：" + request.getServletPath());
        logger.warn("请求方式：" + request.getMethod());
        logger.warn("异常信息：" + e.getMessage());
        logger.warn("================== 「    异 常 结 束    」 ==================");
        return RT.error(RT.DEFAULT_ERROR_CODE,e.getMessage());
    }

    /**
     *  没有权限
     * @param request 请求信息
     * @param e 异常信息
     * @return 返回处理结果
     */
    @ExceptionHandler(value = UnauthorizedException.class)//指定拦截类型
    public RT accountNotHavePermission(HttpServletRequest request, HttpServletResponse response,Exception e){
        logger.warn("================== 「    权 限 不 足    」 ==================");
        logger.warn("请求路径：" + request.getServletPath());
        logger.warn("请求方式：" + request.getMethod());
        logger.warn("异常信息：" + e.getMessage());
        logger.warn("================== 「    异 常 结 束    」 ==================");
        if(request.getMethod().equals("GET")){
            try {
                response.sendRedirect("/login/permission");
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return RT.error(RT.DEFAULT_NOT_PERMISSION,e.getMessage());
    }

    /**
     *  链接超时
     * @param request 请求信息
     * @param e 异常信息
     * @return 返回处理结果
     */
    @ExceptionHandler(value = SocketTimeoutException.class)//指定拦截类型
    public RT socketTimeoutException(HttpServletRequest request,Exception e){
        logger.warn("================== 「    链 接 超 时    」 ==================");
        /*logger.warn("请求路径：" + request.getServletPath());
        logger.warn("请求方式：" + request.getMethod());
        logger.warn("异常信息：" + e.getMessage());*/
        logger.warn("================== 「    异 常 结 束    」 ==================");
        return RT.error(RT.DEFAULT_ERROR_CODE,e.getMessage());
    }

    /**
     *  页面视图有误
     * @param request 请求信息
     * @param e 异常信息
     * @return 返回处理结果
     */
    @ExceptionHandler(value = { TemplateInputException.class,ParseException.class,SpelParseException.class,TemplateProcessingException.class})//指定拦截类型
    public RT spelParseException(HttpServletRequest request,Exception e){
        logger.warn("================== 「    视 图 错 误    」 ==================");
        logger.warn("请求路径：" + request.getServletPath());
        logger.warn("请求方式：" + request.getMethod());
        logger.warn("异常信息：" + e.getMessage());
        logger.warn("================== 「    异 常 结 束    」 ==================");
        return RT.error(RT.DEFAULT_ERROR_CODE,e.getMessage());
    }

    /**
     * 异常拦截
     * @param request 请求
     * @param e 异常
     * @return 异常数据
     */
    @ExceptionHandler(value = Exception.class)//指定拦截类型
    public RT defaultErrorHandler(HttpServletRequest request,Exception e){
        // 打印数据异常信息
        RequestUtil.printRequestErrorInfo(logger,request, e);
        return RT.error(RT.DEFAULT_ERROR_CODE,e.toString());
    }

}
